/**
 * Created by IntelliJ IDEA.
 * User: Ian
 * Date: Jan 19, 2011
 * Time: 9:20:25 PM
 * To change this template use File | Settings | File Templates.
 */
/**
 *
 * @param {Game} game
 */
Ball = function(game, x, y, r) {
  var that = this;
  var game_ = game;
  var radius_ = r || 10;
  var pos_ = new Vec2(x,y);
  var lastPos_ = new Vec2(x,y-1);

  var groundTangent_ = new Vec2(0,0); 

  that.Update = function(tick) {
    var temp = pos_.Copy();
    pos_ = pos_.Add(pos_.Subtract(lastPos_)).Add(game.GetGravity());
    lastPos_ = temp;
  }

  /**
   *
   * @param {Image} ctx
   */
  that.CheckCollisions = function(ctx) {
    var map = ctx.getImageData(
        Math.round(pos_.x) - radius_,
        Math.round(pos_.y) - radius_,
        radius_ * 2,
        radius_ * 2);


    var radiusSquared = radius_ * radius_;
    var minDistSquared = radiusSquared;
    var closestPoint = new Vec2(0,0);
    var fracX = pos_.x - Math.round(pos_.x);
    var fracY = pos_.y - Math.round(pos_.y);
    var centerPoint = new Vec2(radius_ + fracX, radius_ + fracY);
    for (var x = 0; x < map.width; ++x) {
      for (var y = 0; y < map.height; ++y) {
        var idx = (y * map.width + x) * 4; // 4 elements in each pixel
        idx += 3; // idx is 4th element
        var alpha = map.data[idx];

        var testPoint = new Vec2(x,y);
        if (alpha > 64) {
          // hit!
          var distSquared = centerPoint.DistanceSquaredTo(testPoint);
          if (distSquared < minDistSquared) {
            minDistSquared = distSquared;
            closestPoint = testPoint;
          }
        }
      }
    }

    if (minDistSquared < radiusSquared) {
      var len = Math.sqrt(minDistSquared);
      var adjustAmount = radius_ - len;
      var adjustDirection = centerPoint.Subtract(closestPoint).Normalize();
      pos_ = pos_.Add(adjustDirection.Scale(adjustAmount));

      // This is not in any way correct. The adjustDirection is only vaguely related
      // to the ground normal.
      groundTangent_ = new Vec2(adjustDirection.y, -adjustDirection.x);
    } else {
      groundTangent_ = new Vec2(0,0);
    }

  }

  /**
   *
   * @param {CanvasContext} ctx
   */
  that.Draw = function(ctx) {
    ctx.beginPath();
    ctx.arc(pos_.x, pos_.y, radius_, 0, Math.PI * 2);
    ctx.stroke();
  }

  /**
   * @return {Vec2}
   */
  that.GetPosition = function() {
    return pos_.Copy();
  }

  /**
   *
   * @param {Vec2} vec
   */
  that.Nudge = function(vec) {
    var groundPlaneMagnitude = Math.abs(vec.Dot(groundTangent_));
    pos_ = pos_.Add(vec.Normalize().Scale(groundPlaneMagnitude));
  }
}
